package sw6.visualschedule.persistence;

import com.j256.ormlite.stmt.DeleteBuilder;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.j256.ormlite.stmt.SelectArg;

import sw6.visualschedule.entities.ActivityStatus;

import android.content.Context;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class ActivityStatusRepo extends AbstractDataRepo<ActivityStatus> {
    
    private final static String LOG_NAME = "ActivityStatusService";
    
    /**
     * Initializes the repository
     * @param base the context to run in.
     */
    public ActivityStatusRepo(final Context base) {
        super(ActivityStatus.class);
        
        this.attachBaseContext(base);
    }
    
    /**
     * Delete a status entry.
     */
    public void delete(final int activityId) {
    	try {
			DeleteBuilder<ActivityStatus, Integer> db =  getDao().deleteBuilder();
			
			db.where().eq(ActivityStatus.ACTIVITY_ID_FIELD, activityId);
			getDao().delete(db.prepare());
		} catch (SQLException e) {
			throw new RuntimeException(LOG_NAME, e);
		}
    	
    }
    
    /**
     * Returns a list of status entries recorded on a date.
     * @param date the date to filter by.
     * @return a list of status entries.
     */
    public List<ActivityStatus> getStatusEntries(final Date date) {
        List<ActivityStatus> entries = new ArrayList<ActivityStatus>();

        final Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(date);
        
        calendar.set(GregorianCalendar.HOUR_OF_DAY, 0);
        calendar.set(GregorianCalendar.MINUTE, 0);
        calendar.set(GregorianCalendar.SECOND, 0);
        final Date startDateRange = calendar.getTime();
        
        calendar.set(GregorianCalendar.HOUR_OF_DAY, 23);
        calendar.set(GregorianCalendar.MINUTE, 59);
        calendar.set(GregorianCalendar.SECOND, 59);
        final Date endDateRange = calendar.getTime();
        
        try {
            final QueryBuilder<ActivityStatus, Integer> query = getDao().queryBuilder();
            
            final SelectArg dateClauseStart = new SelectArg();
            final SelectArg dateClauseEnd = new SelectArg();
            
            query.where().between(ActivityStatus.DATETIME_FIELD, dateClauseStart, dateClauseEnd);
            
            final PreparedQuery<ActivityStatus> preparedQuery = query.prepare();    
            
            dateClauseStart.setValue(startDateRange);
            dateClauseEnd.setValue(endDateRange);
            
            entries = getDao().query(preparedQuery);
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }
        
        return entries;
    }
    
    /**
     * Inserts or updates a status entry in the database.
     * @param status the status entry.
     */
    public void insertOrUpdate(final ActivityStatus status) {
        try {
            final QueryBuilder<ActivityStatus, Integer> query = getDao().queryBuilder();
            
            final SelectArg activityClause = new SelectArg();
            final SelectArg datetimeClause = new SelectArg();
            
            query.where().eq(ActivityStatus.ACTIVITY_ID_FIELD, activityClause).and().eq(ActivityStatus.DATETIME_FIELD, datetimeClause);
            
            final PreparedQuery<ActivityStatus> preparedQuery = query.prepare();
            
            activityClause.setValue(status.getActivity().getId());
            datetimeClause.setValue(status.getDateTime());
            
            final List<ActivityStatus> entries = getDao().query(preparedQuery);
            if (entries.isEmpty()) {
                getDao().create(status);
            } else {
                entries.get(0).setStatus(status.getStatus());
                getDao().update(entries.get(0));
            }
        } catch (SQLException e) {
        	throw new RuntimeException(LOG_NAME, e);
        }    
    }
}
